﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "TemporaryDimensionHandlerFactory.h"
#include "ITemporaryDimensionManager.h"

#include "IUiDocumentViewManager.h"
#include "GbmpNew.h"

#include "TemporaryDimensionDefine.h"
#include "LinearTemporaryDimensionHandler.h"
#include "RadiusTemporaryDimensionHandler.h"
#include "CentralAngleTemporaryDimensionHandler.h"
#include "RotationTemporaryDimensionHandler.h"
#include "RectangleTemporaryDimensionHandler.h"
#include "ITemporaryDimensionContext.h"
#include "TemporaryDimensionContext.h"
#include "TriangleTemporaryDimensionHandler.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"


using namespace gcmp;

namespace
{
    bool AreContextAndHandlerMatched(const std::type_info& tiCtx, const std::type_info& tiHandler)
    {
        static std::map<size_t, size_t> typeTable;
        if (typeTable.empty())
        {
            typeTable =
            {
                { typeid(LinearTemporaryDimensionContext).hash_code(), typeid(LinearTemporaryDimensionHandler).hash_code() },
                { typeid(RadiusTemporaryDimensionContext).hash_code(), typeid(RadiusTemporaryDimensionHandler).hash_code() },
                { typeid(CentralAngleTemporaryDimensionContext).hash_code(), typeid(CentralAngleTemporaryDimensionHandler).hash_code() },
                { typeid(RotationTemporaryDimensionContext).hash_code(), typeid(RotationTemporaryDimensionHandler).hash_code() },
                { typeid(RectangleTemporaryDimensionContext).hash_code(), typeid(RectangleTemporaryDimensionHandler).hash_code() },
                { typeid(TriangleTemporaryDimensionContext).hash_code(), typeid(TriangleTemporaryDimensionHandler).hash_code() }
            };
        }

        auto iter = typeTable.find(tiCtx.hash_code());
        if (iter == typeTable.end())
        {
            return false;
        }

        return tiHandler.hash_code() == iter->second;
    }

    static TemporaryDimensionHandlerFactory elementEditHelperFactory;
}

TemporaryDimensionHandlerFactory::TemporaryDimensionHandlerFactory()
{
    ITemporaryDimensionManager::Get()->SetHandlerFactory(this);
}

TemporaryDimensionHandlerFactory::~TemporaryDimensionHandlerFactory()
{
    ITemporaryDimensionManager::Get()->SetHandlerFactory(nullptr);
}

TemporaryDimensionHandlerFactory* TemporaryDimensionHandlerFactory::GetInstance()
{
    return &elementEditHelperFactory;
}

gcmp::OwnerPtr<ITemporaryDimensionHandler> TemporaryDimensionHandlerFactory::UpdateOrCreateHandler(
    const ITemporaryDimensionContext* pCtx, ITemporaryDimensionHandler* pHandler /*= nullptr*/)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pCtx, L"pCtx为空!",L"GDMPLab",L"2024-03-30");

    IUiView* pCurrentView = IUiDocumentViewManager::Get()->GetCurrentUiView();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pCurrentView, L"pCurrentView为空",L"GDMPLab",L"2024-03-30");

    const std::type_info& tiCtx = typeid(*pCtx);
    if (pHandler && AreContextAndHandlerMatched(tiCtx, typeid(*pHandler)))
    {
        //if (pHandler->IsEditValueValid() && !pHandler->IsInInputState())
        //{
        //    pHandler->HideInputWidget();
        //}

        pHandler->UpdateConfig(pCtx);
        return nullptr;
    }

    OwnerPtr<ITemporaryDimensionHandler> opHandler = nullptr;
    if (tiCtx.hash_code() == typeid(LinearTemporaryDimensionContext).hash_code())
    {
        const LinearTemporaryDimensionContext* pLinearCtx = dynamic_cast<const LinearTemporaryDimensionContext*>(pCtx);
        opHandler = NEW_AS_OWNER_PTR(LinearTemporaryDimensionHandler, pCurrentView);
    }
    else if (tiCtx.hash_code() == typeid(RadiusTemporaryDimensionContext).hash_code())
    {
        const RadiusTemporaryDimensionContext* pRadiusCtx = dynamic_cast<const RadiusTemporaryDimensionContext*>(pCtx);
        opHandler = NEW_AS_OWNER_PTR(RadiusTemporaryDimensionHandler, pCurrentView);
    }
    else if (tiCtx.hash_code() == typeid(CentralAngleTemporaryDimensionContext).hash_code())
    {
        opHandler = NEW_AS_OWNER_PTR(CentralAngleTemporaryDimensionHandler, pCurrentView);
    }
    else if (tiCtx.hash_code() == typeid(RotationTemporaryDimensionContext).hash_code())
    {
        opHandler = NEW_AS_OWNER_PTR(RotationTemporaryDimensionHandler, pCurrentView);
    }
    else if (tiCtx.hash_code() == typeid(RectangleTemporaryDimensionContext).hash_code())
    {
        opHandler = NEW_AS_OWNER_PTR(RectangleTemporaryDimensionHandler, pCurrentView);
    }
    else if (tiCtx.hash_code() == typeid(TriangleTemporaryDimensionContext).hash_code())
    {
        opHandler = NEW_AS_OWNER_PTR(TriangleTemporaryDimensionHandler, pCurrentView);
    }
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opHandler, L"没有匹配的Handler：" + StringUtil::ToWString(tiCtx.name()),L"GDMPLab",L"2024-03-30");
    opHandler->UpdateConfig(pCtx);
    return opHandler;
}

bool gcmp::TemporaryDimensionHandlerFactory::GetCurrentHandlerCoordinate(const ITemporaryDimensionHandler *pTemporaryDimensionHandler, Coordinate3d &curCoord) const
{
    const TemporaryDimensionHandler *pCommonHandler = dynamic_cast<const TemporaryDimensionHandler *>(pTemporaryDimensionHandler);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pCommonHandler, L"pCommonHandler is null",L"GDMPLab",L"2024-03-30");
    return pCommonHandler->GetCoordinate(curCoord);
}

